package com.oop.example.processing;

import com.oop.example.data.EntryPOJO;
import com.oop.example.data.HibernateUtil;
import com.oop.example.utils.Utils;
import com.oop.example.xml.LabelDictionary;
import com.oop.example.xml.LingvoXML;
import com.oop.example.xml.ObjectFactory;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JProgressBar;
import javax.swing.text.JTextComponent;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.hibernate.Query;
import org.hibernate.classic.Session;

/**
 * Выгрузка словаря в XML файл
 *
 * @author SalAA
 */
public class ExportTask implements Runnable {

    protected ObjectFactory factory = new ObjectFactory();
    protected File outFile = null;
    protected boolean stop = false;
    protected String indexLanguage = "";
    protected String contentLanguage = "";
    protected String numeratorDictionary = "";
    protected String sortingType = "";
    protected String dictionaryName = "";
    protected JTextComponent indicator = null;
    protected boolean labels = false;
    protected boolean format = false;
    protected JProgressBar progress;
    protected ProcessingFactory processingFactory = new ProcessingFactory();

    public void setIndexLanguage(String indexLanguage) {
        this.indexLanguage = indexLanguage;
    }

    public void setContentLanguage(String contentLanguage) {
        this.contentLanguage = contentLanguage;
    }

    public void setNumeratorDictionary(String numeratorDictionary) {
        this.numeratorDictionary = numeratorDictionary;
    }

    public void setSortingType(String sortingType) {
        this.sortingType = sortingType;
    }

    public void setDictionaryName(String dictionaryName) {
        this.dictionaryName = dictionaryName;
    }

    public void setTextIndicator(JTextComponent indicator) {
        this.indicator = indicator;
    }

    public void setExportLabels(boolean labels) {
        this.labels = labels;
    }

    public void setFormatOutput(boolean format) {
        this.format = format;
    }

    public void setProgressIndicator(JProgressBar progress) {
        this.progress = progress;
    }

    public void stop() {
        this.stop = true;
    }

    public boolean isStoped() {
        return stop;
    }

    public void setFile(File outFile) {
        this.outFile = outFile;
    }
    private LingvoXML xml = factory.createLingvoXML();
    private LingvoXML.Dictionary dictionary = factory.createLingvoXMLDictionary();

    @Override
    public void run() {
        int counter = 0;
        int max = 0;
        indicator.setText("Извлечение массива данных из БД");
        ArrayList<EntryPOJO> items = new ArrayList<EntryPOJO>();
        try {
            Session openSession = HibernateUtil.getSessionFactory().openSession();
            Query createQuery = openSession.createQuery("select a from EntryPOJO a order by a.ID");
            List list = createQuery.list();
            max = list.size();
            progress.setMaximum(max);
            for (Object o : list) {
                counter++;
                progress.setValue(counter);
                if (o instanceof EntryPOJO) {
                    EntryPOJO pojo = (EntryPOJO) o;
                    items.add(pojo);
                    if (stop) {
                        return;
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
        int count = 0;
        //Формирование массива Entry
        indicator.setText("Парсинг");
        counter = 0;
        max = items.size();

        for (EntryPOJO pojo : items) {
            counter++;
            progress.setValue(counter);
            progress.setToolTipText("" + counter + " из " + max);
            try {
                Preparer preparer = processingFactory.getPreparer();
                preparer.setSource(pojo.getContent());
                preparer.clean();
                preparer.markLabels(Utils.getLabelDictionary());
                //
                Parser parser = processingFactory.getParser();
                parser.setString(preparer.getString());
                if (parser.isApplicable()) {
                    parser.parse();
                    dictionary.getEntry().add(parser.getEntry());
                    if (parser.getAlternativeEntrys() != null && !parser.getAlternativeEntrys().isEmpty()) {
                        dictionary.getEntry().addAll(parser.getAlternativeEntrys());
                    }
                } else {
                    count++;
                }
            } catch (Exception ex) {
                count++;
            }
            if (stop) {
                return;
            }
        }

        indicator.setText("Заполнение параметров словаря");
        try {
            dictionary.setContentLanguage(contentLanguage);
            dictionary.setDictionaryName(dictionaryName);
            dictionary.setIndexLanguage(indexLanguage);
            dictionary.setNumeratorDictionary(numeratorDictionary);
            dictionary.setSortingType(sortingType);
            if (labels) {
                Properties labelDictionaryProps = Utils.getLabelDictionary();
                LabelDictionary labelDictionary = factory.createLabelDictionary();
                for (String s : labelDictionaryProps.stringPropertyNames()) {
                    LabelDictionary.Entry labelDictionaryEntry = factory.createLabelDictionaryEntry();
                    labelDictionaryEntry.setLabel(s);
                    labelDictionaryEntry.setTranslation(labelDictionaryProps.getProperty(s));
                    labelDictionary.getEntry().add(labelDictionaryEntry);
                }
                dictionary.setLabelDictionary(labelDictionary);
            }
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
        //Сохранение в файл
        indicator.setText("Сохранение в файл");
        try {
            xml.setVersion(2);
            xml.setDictionary(dictionary);
            JAXBContext ctx = JAXBContext.newInstance(LingvoXML.class);
            Marshaller marshaller = ctx.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, format);
            StringWriter sw = new StringWriter();
            marshaller.marshal(xml, sw);
            StringBuffer sb = null;
            if (format) {
                sb = removeSpaces(sw.getBuffer());
            } else {
                sb = sw.getBuffer();
            }
            sw.close();
            sw = null;
            sb = processingFactory.getUnloadProcessor().process(sb);
            write(outFile, sb);
        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
        indicator.setText("Готово! Ошибок разбора: " + count);
    }

    public static StringBuffer removeSpaces(CharSequence htmlString) {
        Pattern patt = Pattern.compile(">( )*(\n)( )*<");
        Matcher m = patt.matcher(htmlString);
        StringBuffer sb = new StringBuffer(htmlString.length());
        while (m.find()) {
            String text = m.group(1);
            text = ">\n<";
            m.appendReplacement(sb, Matcher.quoteReplacement(text));
        }
        m.appendTail(sb);
        return sb;
    }

    public static void write(File f, StringBuffer sb) {
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
            out.write(sb.toString());
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
}
